import 'dart:math';

import 'package:flustars/flustars.dart';
import 'package:fluttercalcpokers/util/biz_util.dart';
import 'package:fluttercalcpokers/util/comm_util.dart';

import 'bean/card_bean.dart';
import 'bean/player_bean.dart';
import 'bean/texas_bean.dart';
import 'card_power_util.dart';
import 'card_util.dart';

class CalculateUtils {
  static int times = 10000;

  static void setBaseTimes(int t) {
    times = t;
  }

  ///计算德州扑克胜率
  static List<PlayerBean> execute(List<PlayerBean> players, TexasBean curBean) {
    //准备工作，清除部分记录数据
    for (var i = 0; i < players.length; i++) {
      players[i].clearRecord();
    }
    var drawTimes = 0; //平局的次数
    for (var i = 0; i < times; i++) {
      BizUtils.clearCards();
      //1.1添加已经存在的底牌
      BizUtils.addCards(curBean.flops);
      BizUtils.addCard(curBean.turn);
      BizUtils.addCard(curBean.river);
      //1.2添加已经存在的手牌
      for (var i = 0; i < players.length; i++) {
        BizUtils.addCards(players[i].hands);
      }
      //2.补全未生成的手牌(随机生成)
      List<PlayerBean> tempPlayers = new List();
      for (var i = 0; i < players.length; i++) {
        PlayerBean tempPlayer;
        if (players[i].handsList.isEmpty) {
          tempPlayer = createHandsByRandom(players[i]);
        } else {
          tempPlayer = createHandsByList(players[i]);
        }
        tempPlayers.add(tempPlayer);
      }
      //3.补全未生成的底牌(随机生成)
      TexasBean tempTexas = new TexasBean();
      tempTexas.flops.addAll(curBean.flops);
      if (curBean.flops.length < 3) {
        tempTexas.flops.addAll(BizUtils.randomCards(3 - curBean.flops.length));
      }
      if (curBean.turn == null) {
        tempTexas.turn = BizUtils.randomCards(1).first;
      } else {
        tempTexas.turn = curBean.turn;
      }
      if (curBean.river == null) {
        tempTexas.river = BizUtils.randomCards(1).first;
      } else {
        tempTexas.river = curBean.river;
      }
      //计算单次牌力,并记录玩家牌型和牌力
      for (var i = 0; i < tempPlayers.length; i++) {
        var cardType = CardUtils.recogniseType(tempPlayers[i], tempTexas);
        List<CardBean> cardResults =
            CardUtils.getCardResultList(tempPlayers[i], tempTexas);
        String strengthHex = CardPowerUtils.getCardPower(cardType, cardResults);
        players[i].strength = CommUtils.hexToInt(strengthHex); //记录牌力
        players[i].addTypeCount(cardType); //记录牌型
      }
      List<int> maxIndexList = new List();
      maxIndexList.add(0);
      //循环比较牌力
      for (var i = 1; i < players.length; i++) {
        if (players[i].strength > players[maxIndexList.first].strength) {
          maxIndexList.clear();
          maxIndexList.add(i);
        } else if (players[i].strength ==
            players[maxIndexList.first].strength) {
          maxIndexList.add(i);
        }
      }
      if (maxIndexList.length == 1) {
        //记录这一次胜利的玩家
        players[maxIndexList.first].winCount++;
      } else {
        //记录这一次平局的玩家
        for (var i = 0; i < maxIndexList.length; i++) {
          players[maxIndexList[i]].drawCount += 1 / maxIndexList.length;
        }
      }
    }
    //计算统计的胜率
    for (var i = 0; i < players.length; i++) {
      players[i].winRate =
          NumUtil.getNumByValueDouble(players[i].winCount / times, 4);
    }
    //计算统计的平局
    for (var i = 0; i < players.length; i++) {
      players[i].drawRate =
          NumUtil.getNumByValueDouble(players[i].drawCount / times, 4);
    }
    optimizeOdds(players);
    return players;
  }

  static PlayerBean createHandsByRandom(PlayerBean player) {
    PlayerBean tempPlayer = new PlayerBean();
    tempPlayer.hands.addAll(player.hands);
    var count = 2 - player.hands.length;
    if (count != 0) {
      tempPlayer.hands.addAll(BizUtils.randomCards(count));
    }
    return tempPlayer;
  }

  static PlayerBean createHandsByList(PlayerBean player) {
    PlayerBean tempPlayer = new PlayerBean();
    if (!isLegalHandsList(player)) return tempPlayer;
    List<CardBean> hands;
    var rng = new Random();
    do {
      String handsStr = player.handsList[rng.nextInt(player.handsList.length)];
      hands = CardBean.str2Hands(handsStr);
    } while (BizUtils.isExitCard(hands[0]) || BizUtils.isExitCard(hands[1]));
    tempPlayer.hands.addAll(hands);
    return tempPlayer;
  }

  static bool isLegalPlayers(List<PlayerBean> players) {
    for (var i = 0; i < players.length; i++) {
      if (!isLegalHandsList(players[i])) {
        return false;
      }
    }
    return true;
  }

  static bool isLegalHandsList(PlayerBean player) {
    List<CardBean> hands;
    for (var i = 0; i < player.handsList.length; i++) {
      hands = CardBean.str2Hands(player.handsList[i]);
      if (!BizUtils.isExitCard(hands[0]) && !BizUtils.isExitCard(hands[1])) {
        return true;
      }
    }
    return false;
  }

  ///优化赔率没有总和100%
  static void optimizeOdds(List<PlayerBean> players) {
    double totalRate = players
        .map((bean) => bean.winRate + bean.drawRate)
        .reduce((value, element) => value + element);
    if (totalRate > 1) {
      if (players.first.drawRate == 0) {
        players.first.winRate -= totalRate - 1;
      } else {
        players.first.drawRate -= totalRate - 1;
      }
    } else {
      if (players.last.drawRate == 0) {
        players.last.winRate += 1 - totalRate;
      } else {
        players.last.drawRate += 1 - totalRate;
      }
    }
  }
}
